package interfaze;

import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import logic.AlreadyRegisteredException;
import logic.PlayerNotFoundException;
import logic.Utilities;

@SuppressWarnings("serial")
public class Login extends JFrame implements ActionListener, MouseListener {

	private final int WIDTH = 1280;		//JFrames width.
	private final int HEIGHT = 720;		//JFrames height.
	private final int FULLSCREEN_WIDTH = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();		//Display's width.
	private final int FULLSCREEN_HEIGHT = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();	//Display's height.
	private JPanel panel = new JPanel();						//Auxiliary panel.
	private JLabel lUserName = new JLabel("User Name:");		//User name label.
	private JTextField tfUserName = new JTextField();			//User name text field.
	private JLabel lPassword = new JLabel("Password:");			//Password label.
	private JPasswordField tfPassword = new JPasswordField();	//Password password field.
	private JButton bSignIn = new JButton("Sign in");			//Sign in button.
	private JButton bSignUp = new JButton("Sign up");			//Sign up button.
	private JButton bExit = new JButton("Exit");				//Exit-Cancel button.
	private Font font;										//The font that is going to be used by all the buttons labels and text fields.
	private JLabel background = new JLabel();					//The background of the JFrame.
	private boolean signUpMode = false;							//The flag for the sign up mode.
	
	public Login() {
		
		//Sets JFrames configuration.
		this.setLayout(null);
		this.setBounds((FULLSCREEN_WIDTH / 2) - (WIDTH / 2), (FULLSCREEN_HEIGHT / 2) - (HEIGHT / 2), WIDTH, HEIGHT);
		this.setTitle("Login");
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		//Sets the font that is going to be used for all the buttons and labels.
		font = new Font("Helvetica", Font.PLAIN, 13);
		
		//Setting the background.
		Image image = Utilities.loadImage("res/LoginBackground.png");
		background.setIcon(new ImageIcon(image));
		background.setBounds(0, 0, image.getWidth(null), image.getHeight(null));
		
		//Sets all the JFrames components boundaries, fonts and so on.
		lUserName.setFont(font);
		lUserName.setForeground(Color.WHITE);
		lUserName.setBounds(25, 25, 75, 25);
		
		tfUserName.setFont(font);
		tfUserName.setBounds(lUserName.getX() + lUserName.getWidth() + 5, lUserName.getY(), 130, 25);
		
		lPassword.setFont(font);
		lPassword.setForeground(Color.WHITE);
		lPassword.setBounds(lUserName.getX(), lUserName.getY() + lUserName.getHeight() + 5, lUserName.getWidth(), lUserName.getHeight());
		tfPassword.setFont(font);
		tfPassword.setBounds(tfUserName.getX(), lPassword.getY(), 130, 25);
		
		bSignIn.setFont(font);
		bSignIn.setBounds(lPassword.getX(), lPassword.getY() + lPassword.getHeight() + 25, 100, 25);
		
		bSignUp.setFont(font);
		bSignUp.setBounds(bSignIn.getX() + bSignIn.getWidth() + 15, bSignIn.getY(), 100, 25);
		
		bExit.setFont(font);
		bExit.setBounds(bSignUp.getX() + bSignUp.getWidth() + 15, bSignUp.getY(), 100, 25);
		
		panel.setBounds(this.WIDTH/2 - (bExit.getX() + bExit.getWidth() + 25)/2,
				this.HEIGHT/2 - (bExit.getY() + bExit.getHeight() + 25)/2,
				bExit.getX() + bExit.getWidth() + 25, bExit.getY() + bExit.getHeight() + 25);
		
		//Set layouts coordinates to null in order to work with absolute coordinates.
		panel.setLayout(null);
		panel.setOpaque(false);
		
		//Adds the components to the central panel.
		panel.add(lUserName);
		panel.add(tfUserName);
		
		panel.add(lPassword);
		panel.add(tfPassword);
		
		panel.add(bSignIn);
		panel.add(bSignUp);
		panel.add(bExit);
		
		//Adds the components to the JFrame.
		this.add(panel);
		this.add(background);
		
		//Sets the JFrame visible.
		this.setVisible(true);
		
		//Adds the components listeners.
		bSignIn.addActionListener(this);
		bSignIn.addMouseListener(this);
		bSignUp.addActionListener(this);
		bSignUp.addMouseListener(this);
		bExit.addActionListener(this);
		bExit.addMouseListener(this);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource().equals(bSignIn)) {
			boolean hasAccess = true;
			if(tfUserName.getText().length() > 0 && tfPassword.getPassword().length > 0) {
				try {
					//Search for the user in the database.
					database.Search.isRegistered(tfUserName.getText(), Utilities.charArrayToString(tfPassword.getPassword()));
				} catch (PlayerNotFoundException e1) {
					//Sets the has access flag to false.
					hasAccess = false;
				}
				if(hasAccess) {
					//Disposes this window and redirects to the game.
					this.dispose();
					new SuperArcade2in1(tfUserName.getText());
				}
			}
			if(!hasAccess || (tfUserName.getText().length() == 0 || tfPassword.getPassword().length == 0)) {
				//Shows a incorrect user name or password error message.
				JOptionPane.showMessageDialog(this, "The user name or the password is incorrect. Try again.", "Not found",
						JOptionPane.ERROR_MESSAGE);
				tfUserName.setText("");
				tfPassword.setText("");
			}
		} else if(e.getSource().equals(bSignUp)) {
			if(!signUpMode) {
				//Enters the sign up mode.
				bSignIn.setVisible(false);
				bExit.setText("Cancel");
				signUpMode = true;
			} else {
				boolean valid = true;
				if(tfUserName.getText().length() > 0 && tfPassword.getPassword().length > 0) {
					try {
						//Try to register into database.
						database.Insert.insertPlayer(tfUserName.getText(), Utilities.charArrayToString(tfPassword.getPassword()));
					} catch (AlreadyRegisteredException e1) {
						//if the user name is already registered set the valid flag to false.
						valid = false;
					}
					if(valid) {
						//Exits from sign up mode.
						bSignIn.setVisible(true);
						bExit.setText("Exit");
						signUpMode = false;
					}
				}
				if(!valid) {
					//Show an already registered error message.
					JOptionPane.showMessageDialog(this, "The user name typed is already registered, choose a different one.", "Not Valid",
							JOptionPane.ERROR_MESSAGE);
					tfUserName.setText("");
					tfPassword.setText("");
				} else if(tfUserName.getText().length() == 0 || tfPassword.getPassword().length == 0) {
					//Show an invalid user name or password error message.
					JOptionPane.showMessageDialog(this, "The user name or the password is invalid, please choose a different one.", "Not Valid",
							JOptionPane.ERROR_MESSAGE);
				}
			}
		} else if(e.getSource().equals(bExit)) {
			if(!signUpMode) {
				//Exits from the game.
				System.exit(0);
			} else {
				//Exits from the sign up mode.
				bExit.setText("Exit");
				bSignIn.setVisible(true);
				signUpMode = false;
			}
		}
	}
	
	@Override
	public void mouseEntered(MouseEvent e) {
		//Increases the buttons size when the mouse enters them.
		if(e.getSource().equals(bSignIn)) {
			Utilities.buttonEffect(bSignIn, 5, 1, 1);
		} else if(e.getSource().equals(bSignUp)) {
			Utilities.buttonEffect(bSignUp, 5, 1, 1);
		} else if(e.getSource().equals(bExit)) {
			Utilities.buttonEffect(bExit, 5, 1, 1);
		}
	}

	@Override
	public void mouseExited(MouseEvent e) {
		//Decreases the buttons size when the mouse enters them.
		if(e.getSource().equals(bSignIn)) {
			Utilities.buttonEffect(bSignIn, -5, 1, 1);
		} else if(e.getSource().equals(bSignUp)) {
			Utilities.buttonEffect(bSignUp, -5, 1, 1);
		} else if(e.getSource().equals(bExit)) {
			Utilities.buttonEffect(bExit, -5, 1, 1);
		}
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		
	}
	
	/** Initializes the game.
	 * @param args
	 */
	public static void main(String[] args) {
		new Login();
	}
}
